package com.union.vehicleassistant.app;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.os.Build;
import android.os.Process;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.multidex.MultiDex;

import com.clj.fastble.BleManager;
import com.hjq.bar.TitleBar;
import com.hjq.http.EasyConfig;
import com.hjq.http.config.IRequestInterceptor;
import com.hjq.http.model.HttpHeaders;
import com.hjq.http.model.HttpParams;
import com.hjq.http.request.HttpRequest;
import com.hjq.language.LocaleContract;
import com.hjq.language.MultiLanguages;
import com.hjq.toast.ToastUtils;
import com.hjq.umeng.UmengClient;
import com.jakewharton.processphoenix.ProcessPhoenix;
import com.scwang.smart.refresh.footer.ClassicsFooter;
import com.scwang.smart.refresh.header.ClassicsHeader;
import com.scwang.smart.refresh.layout.SmartRefreshLayout;
import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.mmkv.MMKV;
import com.union.vehicleassistant.R;
import com.union.vehicleassistant.aop.Log;
import com.union.vehicleassistant.http.glide.GlideApp;
import com.union.vehicleassistant.http.model.RequestHandler;
import com.union.vehicleassistant.http.model.RequestServer;
import com.union.vehicleassistant.manager.ActivityManager;
import com.union.vehicleassistant.manager.CacheDataManager;
import com.union.vehicleassistant.other.AppConfig;
import com.union.vehicleassistant.other.CrashHandler;
import com.union.vehicleassistant.other.DebugLoggerTree;
import com.union.vehicleassistant.other.TitleBarStyle;
import com.union.vehicleassistant.other.ToastLogInterceptor;
import com.union.vehicleassistant.other.ToastStyle;
import com.union.vehicleassistant.util.CertificateUtils;
import com.union.vehicleassistant.util.DarkModeUtils;
import com.union.vehicleassistant.util.SettingUtils;
import com.union.vehicleassistant.util.UserUtils;
import com.union.vehicleassistant.util.Utils;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import timber.log.Timber;

/**
 * author : Android 轮子哥
 * github : https://github.com/getActivity/AndroidProject
 * time   : 2018/10/18
 * desc   : 应用入口
 */
public final class AppApplication extends Application {

    static {
        // 设置默认的语种（越早设置越好）
        MultiLanguages.setDefaultLanguage(LocaleContract.getSimplifiedChineseLocale());
    }

    private static volatile AppApplication instance;

    @Log("启动耗时")
    @Override
    public void onCreate() {
        super.onCreate();

        initApp();

        initSdk(instance);

        initBle();
    }

    private void initApp() {
        if (instance == null) {
            synchronized (AppApplication.class) {
                if (null == instance) {
                    instance = this;
                }
            }
        }
    }

    public static Application getApp() {
        if (instance == null) {
            throw new NullPointerException("App is not registered in the manifest");
        } else {
            return instance;
        }
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(MultiLanguages.attach(base));
        MultiDex.install(base);
    }


    @Override
    public void onLowMemory() {
        super.onLowMemory();
        // 清理所有图片内存缓存
        GlideApp.get(this).onLowMemory();
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        // 根据手机内存剩余情况清理图片内存缓存
        GlideApp.get(this).onTrimMemory(level);
    }

    /**
     * 初始化一些第三方框架
     */
    public static void initSdk(Application application) {
        SettingUtils.getInstance().setDefaultMode(null);
        // 设置标题栏初始化器
        TitleBar.setDefaultStyle(new TitleBarStyle());

        // 设置全局的 Header 构建器
        SmartRefreshLayout.setDefaultRefreshHeaderCreator((cx, layout) ->
                new ClassicsHeader(application));
        // 设置全局的 Footer 构建器
        SmartRefreshLayout.setDefaultRefreshFooterCreator((cx, layout) -> new ClassicsFooter(application));
        // 设置全局初始化器
        SmartRefreshLayout.setDefaultRefreshInitializer((cx, layout) -> {
            // 刷新头部是否跟随内容偏移
            layout.setEnableHeaderTranslationContent(true)
                    // 刷新尾部是否跟随内容偏移
                    .setEnableFooterTranslationContent(true)
                    // 加载更多是否跟随内容偏移
                    .setEnableFooterFollowWhenNoMoreData(true)
                    // 内容不满一页时是否可以上拉加载更多
                    .setEnableLoadMoreWhenContentNotFull(false)
                    // 仿苹果越界效果开关
                    .setEnableOverScrollDrag(false);
        });


        Utils.init(application);
        // 初始化吐司
        ToastUtils.init(application, new ToastStyle());
        // 设置调试模式
        ToastUtils.setDebugMode(AppConfig.isDebug());
        // 设置 Toast 拦截器
        ToastUtils.setInterceptor(new ToastLogInterceptor());

        // 本地异常捕捉
        CrashHandler.register(application);

        // 友盟统计、登录、分享 SDK
        UmengClient.init(application, AppConfig.isLogEnable());

        // Bugly 异常捕捉
        CrashReport.initCrashReport(application, AppConfig.getBuglyId(), AppConfig.isDebug());

        // Activity 栈管理初始化
        ActivityManager.getInstance().init(application);

        // MMKV 初始化
        String defaultCacheFolder = CacheDataManager.getDefaultCacheFolder(application, "MMKV");
        MMKV.initialize(application, defaultCacheFolder);

        CertificateUtils.SSLParams sslParams = CertificateUtils.getSslSocketFactory();
        // 网络请求框架初始化
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .callTimeout(15, TimeUnit.SECONDS)
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                .hostnameVerifier(CertificateUtils.UnSafeHostnameVerifier)
                .build();

        EasyConfig.with(okHttpClient)
                // 是否打印日志
                .setLogEnabled(AppConfig.isLogEnable())
                // 设置服务器配置
                .setServer(new RequestServer())
                // 设置请求处理策略
                .setHandler(new RequestHandler(application))
                // 设置请求重试次数
                .setRetryCount(1)
                .setInterceptor(new IRequestInterceptor() {
                    @Override
                    public void interceptArguments(@NonNull HttpRequest<?> httpRequest, @NonNull HttpParams params, @NonNull HttpHeaders headers) {
                        String token = UserUtils.getInstance().getToken();
                        if (!TextUtils.isEmpty(token)) {
                            headers.put("Token", token);
                        }
                        // 添加全局请求头
                        headers.put("deviceOaid", UmengClient.getDeviceOaid());
                        headers.put("versionName", AppConfig.getVersionName());
                        headers.put("versionCode", String.valueOf(AppConfig.getVersionCode()));
                        headers.put("timestamp", String.valueOf(System.currentTimeMillis()));
                    }
                })
                .into();

        // 初始化日志打印
        if (AppConfig.isLogEnable()) {
            Timber.plant(new DebugLoggerTree());
        }

        // 注册网络状态变化监听
        ConnectivityManager connectivityManager = ContextCompat.getSystemService(application, ConnectivityManager.class);
        if (connectivityManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
                @Override
                public void onLost(@NonNull Network network) {
                    Activity topActivity = ActivityManager.getInstance().getTopActivity();
                    if (!(topActivity instanceof LifecycleOwner)) {
                        return;
                    }

                    LifecycleOwner lifecycleOwner = ((LifecycleOwner) topActivity);
                    if (lifecycleOwner.getLifecycle().getCurrentState() != Lifecycle.State.RESUMED) {
                        return;
                    }

                    ToastUtils.show(R.string.common_network_error);
                }
            });
        }

        MultiLanguages.init(application);
        DarkModeUtils.init(application);
        DarkModeUtils.initDarkMode();
    }

    private void initBle() {
        BleManager.getInstance().init(this);
        BleManager.getInstance()
                .enableLog(false)
                .setReConnectCount(3, 5000)
                .setOperateTimeout(5000);
    }

    public static void restartApp() {
        ProcessPhoenix.triggerRebirth(getApp());
    }

    public static void killProcess() {
        Process.killProcess(Process.myPid());
    }
}